import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

import calculator from "./calculator.js";
import { indices, uvs, fwFaces } from "./attributes.js";

let scene,
  camera,
  renderer,
  planeMesh,
  gridHelper,
  wpWidth,
  wpHeight,
  orbitControls;

let activeMesh = null;  // 当前活动的构件
let activeFace = null;  // 编辑的面
let isEditFW = false; // 是否正在编辑模板

let draged = false;

// 创建 Raycaster 和鼠标 Vector2
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

let lastMousePosition = new THREE.Vector3();  // 记录鼠标按下时候的位置

export function initScene(anchor) {
  anchor = anchor || 'body'
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000);

  const container = document.querySelector(anchor);

  wpWidth = container.offsetWidth;
  wpHeight = container.offsetHeight;
  // 创建相机
  camera = new THREE.PerspectiveCamera(90, wpWidth / wpHeight, 0.1, 1000000);
  // camera.position.x = -300;
  // camera.position.y = -300;
  camera.position.z = 300;

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  // 渲染器能够渲染阴影效果
  renderer.shadowMap.enabled = true;
  renderer.setSize(wpWidth, wpHeight);
  container.appendChild(renderer.domElement);

  // 创建一个平面作为底板
  const planeGeometry = new THREE.PlaneGeometry(500000, 500000);
  const planeMaterial = new THREE.MeshStandardMaterial({
    color: 0xffffffff,
    side: THREE.DoubleSide,
    transparent: true,
    opacity: 0,
  });
  planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
  planeMesh.rotation.z = 0.5 * Math.PI;
  planeMesh.position.set(0, 0, 0);
  scene.add(planeMesh);

  // 添加网格辅助器
  gridHelper = new THREE.GridHelper(500000, 200); // 创建一个200单位的网格，细分为50个方格
  gridHelper.rotation.x = 0.5 * Math.PI;
  //gridHelper.position.y = -150;
  scene.add(gridHelper);

  // 方向光
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(10, 10, 10);

  directionalLight.shadow.mapSize.width = 1024; // default
  directionalLight.shadow.mapSize.height = 1024; // default
  directionalLight.shadow.camera.near = 0.05; // default
  directionalLight.shadow.camera.far = 500; // default
  //将范围调大
  directionalLight.shadow.camera.top = 20; /// 这个是生效的属性
  directionalLight.shadow.camera.right = 20;
  directionalLight.shadow.camera.left = -20;
  directionalLight.shadow.camera.bottom = -20;
  directionalLight.castShadow = true;
  scene.add(directionalLight);

  // 环境光
  const ambientLight = new THREE.AmbientLight(0xffffff, 2);
  scene.add(ambientLight);

  // 添加鼠标控制
  orbitControls = new OrbitControls(camera, renderer.domElement);
  // controls.enableDamping = true; // 使得相机移动更加平滑
  orbitControls.dampingFactor = 0.05; // 阻尼效果

  addCube()

  function addCube() {
    const size = { w: 200, h: 100 };

    const vertices = calculator.calcFWvers(size, 0, 0);

    const formWorkGeo = new THREE.BufferGeometry();
    formWorkGeo.setAttribute(
      "position",
      new THREE.BufferAttribute(new Float32Array(vertices), 3)
    );
    formWorkGeo.setIndex(indices);
    formWorkGeo.setAttribute("uv", new THREE.BufferAttribute(uvs, 2));
    formWorkGeo.computeVertexNormals();
    const mesh = new THREE.Mesh(
      formWorkGeo,
      new THREE.MeshStandardMaterial({
        color: 0xff00ff,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0.5,
      })
    );
    mesh.userData = {
      type: "formwork",
    };
    scene.add(mesh);
  }
}

// 渲染场景
export const render = () => {
  orbitControls.update(); // 更新 OrbitControls
  renderer.render(scene, camera);
  requestAnimationFrame(render); // 渲染循环
};


export const regClick = () => {
  const onClick = (event) => {
    if (draged)
      return
    mouse.x = ((event.clientX) / wpWidth) * 2 - 1;
    mouse.y = -((event.clientY) / wpHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster.intersectObjects(scene.children);
    if (intersects.length > 0) {
      const intersect = intersects[0];
      const userData = intersect.object.userData;
      if (userData.type == "formwork") {
        activeMesh = intersect
        const positionArray = intersect.object.geometry.attributes.position.array;
        let arr = Array.from(positionArray)
        const faceArr = to2DArray(to2DArray(arr, 3), 4)

        const points = calculator.calcFaceCenter(faceArr)
        createHotPoint(points)
      } else {
        removeHP()
      }
    }
  };
  // 监听鼠标点击
  window.addEventListener("click", onClick, false);

  function removeHP() {
    activeMesh = null
    const allObj = scene.children
    const hotpoint = allObj.filter(e => e.userData.type == "hotPiont")
    hotpoint.forEach(mesh => {
      scene.remove(mesh)
    })
  }
};

// 拖动改变模板大小
export const regDrag = () => {
  const onMouseDown = (event) => {
    draged = false
    mouse.x = ((event.clientX) / wpWidth) * 2 - 1;
    mouse.y = -((event.clientY) / wpHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObjects(scene.children);
    if (intersects.length > 0) {
      const hotointMesh = intersects.find(intersect => intersect.object.userData.type == 'hotPiont')
      if (hotointMesh) {
        //选中热点
        orbitControls.enabled = false
        isEditFW = true
        activeFace = hotointMesh.object.userData.face
      }
    }

    const plane = raycaster.intersectObject(planeMesh);
    if (plane.length > 0) {
      lastMousePosition = plane[0].point
    }
  }


  const onMouseMove = (event) => {
    if (isEditFW) { // 鼠标选取热点拖拽
      draged = true
      // console.log(activeMesh, activeFace)
      mouse.x = ((event.clientX) / wpWidth) * 2 - 1;
      mouse.y = -((event.clientY) / wpHeight) * 2 + 1;

      // 更新射线投射器
      raycaster.setFromCamera(mouse, camera);

      const intersects = raycaster.intersectObject(planeMesh);

      if (intersects.length > 0) {
        // 获取交点的世界坐标
        const currentMousePosition = intersects[0].point;

        // 计算移动距离
        const disX = currentMousePosition.x - lastMousePosition.x
        const disY = currentMousePosition.y - lastMousePosition.y
        const disZ = currentMousePosition.z - lastMousePosition.z

        // console.log('x:'+disX, 'y:'+disY,'z:'+disZ);

        let distance = 0
        switch (activeFace) {
          case 0:
          case 1:
            distance = disZ
            break;
          case 2:
          case 3:
            distance = disY
            break;
          case 4:
          case 5:
            distance = disX
            break;
        }

        if (Math.abs(distance) >= 50) {
          distance = distance < 0 ? (-100) : 100
          console.warn(activeMesh)
          let geometry = activeMesh.object.geometry;
          let positions = geometry.getAttribute('position');

          let arr = Array.from(positions.array)
          const faceArr = to2DArray(to2DArray(arr, 3), 4)

          let newvectors = calculator.calcNewPositions(activeFace, faceArr, distance)

          newvectors = newvectors.flat(Infinity)

          geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(newvectors), 3))
          geometry.getAttribute('position').needsUpdate = true
          geometry.computeBoundingBox()
          activeMesh.object.updateMatrixWorld()
          
          resetHP(newvectors)

          positions.needsUpdate = true;
          lastMousePosition.copy(currentMousePosition);  // 更新点，重新计算距离
        }

        // positions.needsUpdate = true;
      }

    }

    // event.preventDefault()
    // event.stopPropagation()
  }

  const onMouseUp = (event) => {
    orbitControls.enabled = true
    isEditFW = false
    event.preventDefault()
    event.stopPropagation()
  }

  function resetHP(newvectors) {
    const allObj = scene.children
    const hotpoint = allObj.filter(e => e.userData.type == "hotPiont")
    hotpoint.forEach(mesh => {
      scene.remove(mesh)
    })

    const newfaceArr = to2DArray(to2DArray(newvectors, 3), 4)
    const points = calculator.calcFaceCenter(newfaceArr)
    createHotPoint(points)
  }

  window.addEventListener("mousedown", onMouseDown, false);
  window.addEventListener("mouseup", onMouseUp, false);
  window.addEventListener('mousemove', onMouseMove, false)
}


function createHotPoint(points) {
  points.forEach((point, index) => {
    const geometry = new THREE.BoxGeometry(20, 20, 20);
    const material = new THREE.MeshBasicMaterial({ color: 0xffffff });
    const cube = new THREE.Mesh(geometry, material);
    cube.userData = { type: 'hotPiont', face: index }
    cube.position.set(point[0], point[1], point[2])
    scene.add(cube);
  })
}

function to2DArray(arr, subArrayLength) {
  // 计算二维数组的长度
  const numChunks = Math.ceil(arr.length / subArrayLength);
  // 创建一个新的二维数组
  const newArray = Array(numChunks);

  for (let i = 0; i < newArray.length; i++) {
    newArray[i] = arr.slice(i * subArrayLength, i * subArrayLength + subArrayLength);
  }

  return newArray;
}